home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 290_02 / scan.l < prev    next >
Encoding:
Text File  |  1990-05-12  |  9.7 KB  |  410 lines

  1. /*
  2. **    file:        scan.l
  3. **    purpose:    Scanner for flex input
  4. **    mods:        1989.12.30 - Roberto Artigas Jr
  5. **            Updated this file to match the 'scan.c'
  6. **            more closely. It seems that the same
  7. **            indivitual that had NOT run the 'parse.y'
  8. **            file through BISON/YACC for a while, had
  9. **            ALSO not run 'scan.l' through FLEX/LEX.
  10. */
  11.  
  12. /*
  13.  * Copyright (c) 1987, the University of California
  14.  * 
  15.  * The United States Government has rights in this work pursuant to
  16.  * contract no. DE-AC03-76SF00098 between the United States Department of
  17.  * Energy and the University of California.
  18.  * 
  19.  * This program may be redistributed.  Enhancements and derivative works
  20.  * may be created provided the new works, if made available to the general
  21.  * public, are made available for use by anyone.
  22.  */
  23.  
  24. %{
  25. #include <io.h>
  26. #include <fcntl.h>
  27.  
  28. #include "flexdef.h"
  29. #include "parse.h"
  30. #include "sym.h"
  31. #include "main.h"
  32. #include "misc.h"
  33.  
  34.  
  35. #define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
  36. #define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
  37.  
  38.  
  39. #undef YY_DECL
  40. #define YY_DECL \
  41.     int flexscan( void)
  42.  
  43. #define RETURNCHAR \
  44.     yylval = yytext[0]; \
  45.     return ( CHAR );
  46.  
  47. #define RETURNNAME \
  48.     (void) strcpy( nmstr, yytext ); \
  49.     return ( NAME );
  50.  
  51. #define PUT_BACK_STRING(str, start) \
  52.     for ( i = strlen( str ) - 1; i >= start; --i ) \
  53.         unput(str[i])
  54. %}
  55.  
  56. %x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE
  57. %x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT C_COMMENT_2 ACTION_COMMENT
  58. %x ACTION_STRING PERCENT_BRACE_ACTION
  59.  
  60. WS        [ \t]+
  61.  
  62. OPTWS        [ \t]*
  63.  
  64. NAME        [a-z_][a-z_0-9]*
  65.  
  66. SCNAME        {NAME}
  67.  
  68. ESCSEQ        \\([^\n]|0[0-9]{1,3})
  69.  
  70. %%
  71.     static int bracelevel, didadef;
  72.     int i, cclval;
  73.     char nmdef[MAXLINE], myesc();
  74.  
  75. ^{WS}.*\n        ++linenum; ECHO; /* indented code */
  76. ^#.*\n            ++linenum; ECHO; /* treat as a comment */
  77. ^"/*"            ECHO; BEGIN(C_COMMENT);
  78. ^"%s"(tart)?        return ( SCDECL );
  79. ^"%x"            return ( XSCDECL );
  80. ^"%{".*\n        ++linenum; line_directive_out( stdout ); BEGIN(CODEBLOCK);
  81. {WS}            return ( WHITESPACE );
  82.  
  83. ^"%%".*            {
  84.             sectnum = 2;
  85.             line_directive_out( stdout );
  86.             BEGIN(SECT2PROLOG);
  87.             return ( SECTEND );
  88.             }
  89.  
  90. ^"%"[^sx{%].*\n        {
  91.             fprintf( stderr,
  92.                  "old-style lex command at line %d ignored:\n\t%s",
  93.                  linenum, yytext );
  94.             ++linenum;
  95.             }
  96.  
  97. ^{NAME}            {
  98.             (void) strcpy( nmstr, yytext );
  99.             didadef = false;
  100.             BEGIN(PICKUPDEF);
  101.             }
  102.  
  103. {SCNAME}        RETURNNAME;
  104. ^{OPTWS}\n        ++linenum; /* allows blank lines in section 1 */
  105. \n            ++linenum; return ( '\n' );
  106. .            synerr( "illegal character" ); BEGIN(RECOVER);
  107.  
  108.  
  109. <C_COMMENT>"*/"        ECHO; BEGIN(0);
  110. <C_COMMENT>"*/".*\n    ++linenum; ECHO; BEGIN(0);
  111. <C_COMMENT>[^*\n]+    ECHO;
  112. <C_COMMENT>"*"        ECHO;
  113. <C_COMMENT>\n        ++linenum; ECHO;
  114.  
  115. <CODEBLOCK>^"%}".*\n    ++linenum; BEGIN(0);
  116. <CODEBLOCK>.*\n        ++linenum; ECHO;
  117.  
  118. <PICKUPDEF>{WS}        /* separates name and definition */
  119.  
  120. <PICKUPDEF>[^ \t\n].*    {
  121.             (void) strcpy( nmdef, yytext );
  122.  
  123.             for ( i = strlen( nmdef ) - 1;
  124.                   i >= 0 &&
  125.                   nmdef[i] == ' ' || nmdef[i] == '\t';
  126.                   --i )
  127.                 ;
  128.  
  129.             nmdef[i + 1] = '\0';
  130.  
  131.                         ndinstal( nmstr, nmdef );
  132.             didadef = true;
  133.             }
  134.  
  135. <PICKUPDEF>\n        {
  136.             if ( ! didadef )
  137.                 synerr( "incomplete name definition" );
  138.             BEGIN(0);
  139.             ++linenum;
  140.             }
  141.  
  142. <RECOVER>.*\n        ++linenum; BEGIN(0); RETURNNAME;
  143.  
  144.  
  145. <SECT2PROLOG>.*\n/[^ \t\n]    {
  146.             ++linenum;
  147.             ACTION_ECHO;
  148.             MARK_END_OF_PROLOG;
  149.             BEGIN(SECT2);
  150.             }
  151.  
  152. <SECT2PROLOG>.*\n    ++linenum; ACTION_ECHO;
  153.  
  154. <SECT2>^{OPTWS}\n    ++linenum; /* allow blank lines in section 2 */
  155.  
  156.     /* this horrible mess of a rule matches indented lines which
  157.      * do not contain "/*".  We need to make the distinction because
  158.      * otherwise this rule will be taken instead of the rule which
  159.      * matches the beginning of comments like this one
  160.      */
  161. <SECT2>^{WS}([^/\n]|"/"[^*\n])*("/"?)\n    {
  162.             synerr( "indented code found outside of action" );
  163.             ++linenum;
  164.             }
  165.  
  166. <SECT2>"<"        BEGIN(SC); return ( '<' );
  167. <SECT2>^"^"        return ( '^' );
  168. <SECT2>\"        BEGIN(QUOTE); return ( '"' );
  169. <SECT2>"{"/[0-9]        BEGIN(NUM); return ( '{' );
  170. <SECT2>"{"[^0-9\n][^}\n]*    BEGIN(BRACEERROR);
  171. <SECT2>"$"/[ \t\n]    return ( '$' );
  172.  
  173. <SECT2>{WS}"%{"        {
  174.             bracelevel = 1;
  175.             BEGIN(PERCENT_BRACE_ACTION);
  176.             return ( '\n' );
  177.             }
  178. <SECT2>{WS}"|".*\n    ++linenum; return ( '\n' );
  179.  
  180. <SECT2>^{OPTWS}"/*"    ACTION_ECHO; BEGIN(C_COMMENT_2);
  181.  
  182. <SECT2>{WS}        { /* needs to be separate from following rule due to
  183.                * bug with trailing context
  184.                */
  185.             bracelevel = 0;
  186.             BEGIN(ACTION);
  187.             return ( '\n' );
  188.             }
  189.  
  190. <SECT2>{OPTWS}/\n    {
  191.             bracelevel = 0;
  192.             BEGIN(ACTION);
  193.             return ( '\n' );
  194.             }
  195.  
  196. <SECT2>^{OPTWS}\n    ++linenum; return ( '\n' );
  197.  
  198. <SECT2>^"%%".*        {
  199.             /* guarantee that the SECT3 rule will have something
  200.              * to match
  201.              */
  202.             yyless(1);
  203.             sectnum = 3;
  204.             BEGIN(SECT3);
  205.             return ( EOF ); /* to stop the parser */
  206.             }
  207.  
  208. <SECT2>"["([^\\\]\n]|{ESCSEQ})+"]"    {
  209.             (void) strcpy( nmstr, yytext );
  210.  
  211.             /* check to see if we've already encountered this ccl */
  212.             if ( (cclval = ccllookup( nmstr )) )
  213.                 {
  214.                 yylval = cclval;
  215.                 ++cclreuse;
  216.                 return ( PREVCCL );
  217.                 }
  218.             else
  219.                 {
  220.                 /* we fudge a bit.  We know that this ccl will
  221.                  * soon be numbered as lastccl + 1 by cclinit
  222.                  */
  223.                 cclinstal( nmstr, lastccl + 1 );
  224.  
  225.                 /* push back everything but the leading bracket
  226.                  * so the ccl can be rescanned
  227.                  */
  228.                 PUT_BACK_STRING(nmstr, 1);
  229.  
  230.                 BEGIN(FIRSTCCL);
  231.                 return ( '[' );
  232.                 }
  233.             }
  234.  
  235. <SECT2>"{"{NAME}"}"    {
  236.             register char *nmdefptr;
  237.             char *ndlookup();
  238.  
  239.             (void) strcpy( nmstr, yytext );
  240.             nmstr[yyleng - 1] = '\0';  /* chop trailing brace */
  241.  
  242.             /* lookup from "nmstr + 1" to chop leading brace */
  243.             if ( ! (nmdefptr = ndlookup( nmstr + 1 )) )
  244.                 synerr( "undefined {name}" );
  245.  
  246.             else
  247.                 { /* push back name surrounded by ()'s */
  248.                 unput(')');
  249.                 PUT_BACK_STRING(nmdefptr, 0);
  250.                 unput('(');
  251.                 }
  252.             }
  253.  
  254. <SECT2>[/|*+?.()]    return ( yytext[0] );
  255. <SECT2>.        RETURNCHAR;
  256. <SECT2>\n        ++linenum; return ( '\n' );
  257.  
  258.  
  259. <SC>","            return ( ',' );
  260. <SC>">"            BEGIN(SECT2); return ( '>' );
  261. <SC>">"/"^"        BEGIN(CARETISBOL); return ( '>' );
  262. <SC>{SCNAME}        RETURNNAME;
  263. <SC>.            synerr( "bad start condition name" );
  264.  
  265. <CARETISBOL>"^"        BEGIN(SECT2); return ( '^' );
  266.  
  267.  
  268. <QUOTE>[^"\n]        RETURNCHAR;
  269. <QUOTE>\"        BEGIN(SECT2); return ( '"' );
  270.  
  271. <QUOTE>\n        {
  272.             synerr( "missing quote" );
  273.             BEGIN(SECT2);
  274.             ++linenum;
  275.             return ( '"' );
  276.             }
  277.  
  278.  
  279. <FIRSTCCL>"^"/[^-\n]    BEGIN(CCL); return ( '^' );
  280. <FIRSTCCL>"^"/-        return ( '^' );
  281. <FIRSTCCL>-        BEGIN(CCL); yylval = '-'; return ( CHAR );
  282. <FIRSTCCL>.        BEGIN(CCL); RETURNCHAR;
  283.  
  284. <CCL>-/[^\]\n]        return ( '-' );
  285. <CCL>[^\]\n]        RETURNCHAR;
  286. <CCL>"]"            BEGIN(SECT2); return ( ']' );
  287.  
  288.  
  289. <NUM>[0-9]+        {
  290.             yylval = myctoi( yytext );
  291.             return ( NUMBER );
  292.             }
  293.  
  294. <NUM>","            return ( ',' );
  295. <NUM>"}"            BEGIN(SECT2); return ( '}' );
  296.  
  297. <NUM>.            {
  298.             synerr( "bad character inside {}'s" );
  299.             BEGIN(SECT2);
  300.             return ( '}' );
  301.             }
  302.  
  303. <NUM>\n            {
  304.             synerr( "missing }" );
  305.             BEGIN(SECT2);
  306.             ++linenum;
  307.             return ( '}' );
  308.             }
  309.  
  310.  
  311. <BRACEERROR>"}"        synerr( "bad name in {}'s" ); BEGIN(SECT2);
  312. <BRACEERROR>\n        synerr( "missing }" ); ++linenum; BEGIN(SECT2);
  313.  
  314.  
  315. <PERCENT_BRACE_ACTION>{OPTWS}"%}".*    bracelevel = 0;
  316. <PERCENT_BRACE_ACTION>.*        ACTION_ECHO;
  317. <PERCENT_BRACE_ACTION>\n        {
  318.             ++linenum;
  319.             ACTION_ECHO;
  320.             if ( bracelevel == 0 )
  321.                 {
  322.                 fputs( "\tYY_BREAK\n", temp_action_file );
  323.                 BEGIN(SECT2);
  324.                 }
  325.             }
  326.  
  327. <ACTION>"{"        ACTION_ECHO; ++bracelevel;
  328. <ACTION>"}"        ACTION_ECHO; --bracelevel;
  329. <ACTION>[^{}"'/\n]+    ACTION_ECHO;
  330. <ACTION>"/*"        ACTION_ECHO; BEGIN(ACTION_COMMENT);
  331. <ACTION>"'"([^'\\\n]|\\.)*"'"    ACTION_ECHO; /* character constant */
  332. <ACTION>\"        ACTION_ECHO; BEGIN(ACTION_STRING);
  333. <ACTION>\n        {
  334.             ++linenum;
  335.             ACTION_ECHO;
  336.             if ( bracelevel == 0 )
  337.                 {
  338.                 fputs( "\tYY_BREAK\n", temp_action_file );
  339.                 BEGIN(SECT2);
  340.                 }
  341.             }
  342. <ACTION>.        ACTION_ECHO;
  343.  
  344. <ACTION_COMMENT>"*/"    ACTION_ECHO; BEGIN(ACTION);
  345. <ACTION_COMMENT>[^*\n]+    ACTION_ECHO;
  346. <ACTION_COMMENT>"*"    ACTION_ECHO;
  347. <ACTION_COMMENT>\n    ++linenum; ACTION_ECHO;
  348. <ACTION_COMMENT>.    ACTION_ECHO;
  349.  
  350. <C_COMMENT_2>"*/"    ACTION_ECHO; BEGIN(SECT2);
  351. <C_COMMENT_2>"*/".*\n    ++linenum; ACTION_ECHO; BEGIN(SECT2);
  352. <C_COMMENT_2>[^*\n]+    ACTION_ECHO;
  353. <C_COMMENT_2>"*"    ACTION_ECHO;
  354. <C_COMMENT_2>\n        ++linenum; ACTION_ECHO;
  355.  
  356. <ACTION_STRING>[^"\\\n]+    ACTION_ECHO;
  357. <ACTION_STRING>\\.    ACTION_ECHO;
  358. <ACTION_STRING>\n    ++linenum; ACTION_ECHO;
  359. <ACTION_STRING>\"    ACTION_ECHO; BEGIN(ACTION);
  360. <ACTION_STRING>.    ACTION_ECHO;
  361.  
  362.  
  363. <SECT2,QUOTE,CCL>{ESCSEQ}    {
  364.             yylval = myesc( yytext );
  365.             return ( CHAR );
  366.             }
  367.  
  368. <FIRSTCCL>{ESCSEQ}    {
  369.             yylval = myesc( yytext );
  370.             BEGIN(CCL);
  371.             return ( CHAR );
  372.             }
  373.  
  374.  
  375. <SECT3>.|\n        {
  376.             register int numchars;
  377.  
  378.             /* black magic - we know the names of a flex scanner's
  379.              * internal variables.  We cap the input buffer with
  380.              * an end-of-string and dump it to the output.
  381.              */
  382.             YY_DO_BEFORE_SCAN; /* recover from setting up yytext */
  383.  
  384. #ifdef FLEX_FAST_SKEL
  385.             fputs( yy_c_buf_p + 1, stdout );
  386. #else
  387.             yy_ch_buf[yy_e_buf_p + 1] = '\0';
  388.  
  389.             /* ignore the first character; it's the second '%'
  390.              * put back by the yyless(1) above
  391.              */
  392.             fputs( yy_ch_buf + yy_c_buf_p + 1, stdout );
  393. #endif
  394.  
  395.             /* if we don't do this, the data written by write()
  396.              * can get overwritten when stdout is finally flushed
  397.              */
  398.             (void) fflush( stdout );
  399.  
  400.             while ( (numchars = read( fileno(yyin), yy_ch_buf,
  401.                           YY_BUF_MAX )) > 0 )
  402.                 (void) write( fileno(stdout), yy_ch_buf, numchars );
  403.     
  404.             if ( numchars < 0 )
  405.                 flexerror( "fatal read error in section 3" );
  406.  
  407.             return ( EOF );
  408.             }
  409. %%
  410.